package com.question.business.role.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.question.business.role.entity.Role;
import com.question.business.role.mapper.RoleMapper;
import com.question.business.role.model.ao.*;
import com.question.business.role.model.vo.*;
import com.question.business.role.service.IRoleMenuService;
import com.question.business.role.service.IRoleService;
import com.question.business.user.service.IUserRoleService;
import com.question.common.constants.NumberConstants;
import com.question.common.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 角色服务实现类
 *
 * @author star
 * @since 2023-09-13
 */
@Slf4j
@Service
@AllArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    private final IRoleMenuService roleMenuService;

    private final IUserRoleService userRoleService;

    /**
     * 角色分页查询
     *
     * @param ao 请求参数
     * @return Page<RoleVO> 响应参数
     */
    @Override
    public Page<RoleVO> queryRolePage(RolePageAO ao) {
        return baseMapper.queryRolePage(ao.createPage(), ao);
    }

    /**
     * 角色明细查询
     *
     * @param id 角色ID
     * @return RoleDetailVO 响应参数
     */
    @Override
    public RoleDetailVO queryRoleDetail(String id) {
        Role entity = super.getById(id);
        if (Objects.nonNull(entity)) {
            RoleDetailVO vo = new RoleDetailVO();
            BeanUtils.copyProperties(entity, vo);
            vo.setUserIds(userRoleService.queryUserByRoleId(vo.getId()));
            vo.setMenuIds(roleMenuService.queryMenuByRoleId(vo.getId()));
            return vo;
        }
        return null;
    }

    /**
     * 角色新增数据
     *
     * @param ao 请求参数
     * @return RoleAddVO 响应参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RoleAddVO addRole(RoleAddAO ao) {
        if (queryNameExist(ao.getRoleName())) {
            throw new BusinessException("角色名称已存在");
        }
        Role entity = new Role();
        BeanUtils.copyProperties(ao, entity);
        super.save(entity);
        userRoleService.addRoleUser(entity.getId(), ao.getUserIds());
        roleMenuService.addRoleMenu(entity.getId(), ao.getMenuIds());
        RoleAddVO vo = new RoleAddVO();
        vo.setId(entity.getId());
        return vo;
    }

    /**
     * 角色修改数据
     *
     * @param ao 数据
     */
    @Override
    public void updateRole(RoleUpdateAO ao) {
        Role role = super.getById(ao.getId());
        if (Objects.nonNull(role)) {
            if (!ao.getRoleName().equals(role.getRoleName()) && queryNameExist(ao.getRoleName())) {
                throw new BusinessException("角色名称已存在");
            }
            Role entity = new Role();
            BeanUtils.copyProperties(ao, entity);
            entity.setUpdatedTime(LocalDateTime.now());
            super.updateById(entity);
            userRoleService.addRoleUser(ao.getId(), ao.getUserIds());
            roleMenuService.addRoleMenu(ao.getId(), ao.getMenuIds());
        }
    }

    /**
     * 角色删除数据
     *
     * @param id 角色ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRole(String id) {
        super.removeById(id);
        userRoleService.addRoleUser(id, null);
        roleMenuService.addRoleMenu(id, null);
    }

    /**
     * 角色批量删除数据
     *
     * @param ids 请求参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchRole(List<String> ids) {
        for (String id : ids) {
            deleteRole(id);
        }
    }

    /**
     * 用户导出数据
     *
     * @param ao     请求参数
     * @param stream 输出流
     */
    @Override
    public void exportRole(RolePageAO ao, ServletOutputStream stream) {
        ao.setSize(-1);
        List<RoleVO> vos = queryRolePage(ao).getRecords();
        List<RoleExcelVO> list = new ArrayList<>(vos.size());
        for (RoleVO vo : vos) {
            RoleExcelVO excelVo = new RoleExcelVO();
            BeanUtils.copyProperties(vo, excelVo);
            list.add(excelVo);
        }

        ExcelWriter excelWriter = EasyExcelFactory.write(stream).build();
        excelWriter.write(list, EasyExcelFactory.writerSheet(NumberConstants.ZERO).head(RoleExcelVO.class).build());
        excelWriter.finish();
    }

    /**
     * 角色类型启用、停用
     *
     * @param ao 数据
     */
    @Override
    public void enableRole(RoleEnabledAO ao) {
        this.lambdaUpdate().eq(Role::getId, ao.getId()).set(Role::getEnabled, ao.getEnabled()).update(new Role());
    }

    /**
     * 角色下拉列表查询
     *
     * @param ao 请求参数
     * @return List<RoleDropDownVO> 响应参数
     */
    @Override
    public List<RoleDropDownVO> queryRoleDropDown(RoleDropDownAO ao) {
        return baseMapper.queryRoleDropDown(ao);
    }

    /**
     * 查询角色名称是否存在
     *
     * @param roleName 角色名称
     * @return boolean
     */
    private boolean queryNameExist(String roleName) {
        return SqlHelper.retBool(this.lambdaQuery().eq(Role::getRoleName, roleName).count());
    }
}